// ./controllers/auth.controller.js

const User = require('../models/User');
const logger = require('../config/logger.config'); // 引入 logger
const { generateToken } = require('../utils/jwt.util');
const { blacklistToken } = require('../middlewares/auth.middleware');
const { verifyCaptcha } = require('../services/captcha.service');

// -----------------------------------------------------------
// 注册用户
// -----------------------------------------------------------
exports.register = async (req, res) => {
    try {
        const { username, email, password } = req.body;

        // 1. 检查用户是否已存在
        let user = await User.findOne({ $or: [{ username }, { email }] });
        if (user) {
            return res.status(400).send({ message: '用户名或邮箱已存在' });
        }

        // 2. 创建新用户 (密码会在 User.js 模型的 pre('save') 钩子中自动加密)
        user = new User({ username, email, password });
        await user.save();

        // 3. 注册成功，生成 Token 并返回
        const payload = { id: user._id, role: user.role };
        const token = generateToken(payload);

        // 注意：这里手动将 password 设置为 undefined，确保返回响应中没有密码
        user.password = undefined;

        res.status(201).send({
            message: '用户注册成功',
            token: token,
            user: user,
        });
    } catch (error) {
        console.error('注册错误:', error);
        // Mongoose 验证错误处理
        if (error.name === 'ValidationError') {
            const messages = Object.values(error.errors).map((val) => val.message);
            return res.status(400).send({ message: messages.join(', ') });
        }
        res.status(500).send({ message: '服务器内部错误' });
    }
};

/**
 * @swagger
 * /auth/login:
 *   post:
 *     summary: 用户登录
 *     tags: [认证]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - identifier
 *               - password
 *               - captchaId
 *               - captchaText
 *             properties:
 *               identifier:
 *                 type: string
 *                 description: 用户名或邮箱
 *                 example: testuser
 *               password:
 *                 type: string
 *                 format: password
 *                 description: 用户密码
 *                 example: 123456
 *               captchaId:
 *                 type: string
 *                 description: 验证码ID (从 /auth/captcha 获取)
 *               captchaText:
 *                 type: string
 *                 description: 用户输入的验证码文本
 *     responses:
 *       200:
 *         description: 登录成功
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/LoginResponse'
 *       400:
 *         description: 验证码或参数错误
 *       401:
 *         description: 认证失败 (用户名或密码不正确)
 */
exports.login = async (req, res) => {
    try {
        const { identifier, password, captchaId, captchaText } = req.body;

        // --- A. 验证码校验 ---
        if (!captchaId || !captchaText) {
            return res.status(400).send({ message: '验证码ID或验证码文本不能为空' });
        }
        if (!verifyCaptcha(captchaId, captchaText)) {
            return res.status(400).send({ message: '验证码错误' });
        }

        // --- B. 查找用户 (同时查找用户名或邮箱) ---
        // 使用 select('+password') 强制加载 password 字段进行比较
        const user = await User.findOne({
            $or: [{ username: identifier }, { email: identifier }],
        }).select('+password');

        if (!user) {
            logger.warn('登录失败: 用户不存在或密码不正确', { identifier: identifier, ip: req.ip });
            return res.status(401).send({ message: '用户名或密码不正确' });
        }

        // --- C. 密码校验 ---
        // 使用 User Schema 中的 comparePassword 实例方法
        const isMatch = await user.comparePassword(password);
        if (!isMatch) {
            logger.warn('登录失败: 密码错误', { identifier: identifier, userId: user._id, ip: req.ip });
            return res.status(401).send({ message: '用户名或密码不正确' });
        }

        // --- D. 生成 Token ---
        const payload = { id: user._id, role: user.role };
        const token = generateToken(payload);

        // 移除密码和敏感信息再返回
        user.password = undefined;

        logger.info('用户登录成功', { userId: user._id, username: user.username, ip: req.ip });
        res.status(200).send({
            message: '登录成功',
            token: token,
            user: user,
        });
    } catch (error) {
        logger.error('登录请求处理异常', { identifier: req.body.identifier, error: error.message, stack: error.stack });
        res.status(500).send({ message: '服务器内部错误' });
    }
};

// -----------------------------------------------------------
// 用户注销 (Logout)
// -----------------------------------------------------------
exports.logout = async (req, res, next) => {
    try {
        const authHeader = req.headers['authorization'];
        const token = authHeader && authHeader.split(' ')[1];

        if (!token) {
            return res.status(200).send({ message: '已注销' }); // 即使没有 Token 也视为成功注销
        }

        // 1. 解码 Token 获取过期时间 (exp)
        const decoded = jwt.decode(token); // 不需要验证签名，只需要 payload
        if (!decoded || !decoded.exp) {
            return res.status(200).send({ message: 'Token 格式无效，已注销' });
        }

        // 2. 计算 Token 剩余有效期 (秒)
        const now = Math.floor(Date.now() / 1000); // 当前时间 (秒)
        const expirySeconds = decoded.exp - now;

        // 3. 将 Token 加入黑名单
        await blacklistToken(token, expirySeconds);

        logger.info('用户注销成功，Token 已加入黑名单', { userId: req.user ? req.user.id : 'N/A' });

        res.status(200).send({ message: '注销成功' });
    } catch (error) {
        // 记录错误，并传递给统一错误处理
        next(error);
    }
};
